package com.yzjs.base;




import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

import com.google.gson.Gson;
import com.yzjs.config.WxPayConfig;
import com.yzjs.enumeration.*;
import com.yzjs.utils.MapUtil;
import com.yzjs.utils.MoneyUtil;
import com.yzjs.utils.RandomUtil;
import com.yzjs.utils.XmlUtil;
import com.yzjs.wx.WxPayApi;
import com.yzjs.wx.WxPaySignature;
import com.yzjs.wx.request.WxDownloadBillRequest;
import com.yzjs.wx.request.WxOrderQueryRequest;
import com.yzjs.wx.request.WxPayRefundRequest;
import com.yzjs.wx.request.WxPayUnifiedorderRequest;
import com.yzjs.wx.response.*;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import okhttp3.logging.HttpLoggingInterceptor.Level;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.Retrofit.Builder;
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;


public class WxPayServiceImpl extends BestPayServiceImpl {
    private static final Logger log = LoggerFactory.getLogger(WxPayServiceImpl.class);
    private WxPayConfig wxPayConfig;
    private Retrofit retrofit;

    public WxPayServiceImpl() {
        this.retrofit = (new Builder()).baseUrl("https://api.mch.weixin.qq.com/").addConverterFactory(SimpleXmlConverterFactory.create()).client((new okhttp3.OkHttpClient.Builder()).addInterceptor((new HttpLoggingInterceptor()).setLevel(Level.BODY)).build()).build();
    }

    public void setWxPayConfig(WxPayConfig wxPayConfig) {
        this.wxPayConfig = wxPayConfig;
    }

    public PayResponse pay(PayRequest request) {
        WxPayUnifiedorderRequest wxRequest = new WxPayUnifiedorderRequest();
        wxRequest.setOutTradeNo(request.getOrderId());
        wxRequest.setTotalFee(MoneyUtil.Yuan2Fen(request.getOrderAmount()));
        wxRequest.setBody(request.getOrderName());
        wxRequest.setOpenid(request.getOpenid());
        wxRequest.setTradeType(request.getPayTypeEnum().getCode());
        if (request.getPayTypeEnum() == BestPayTypeEnum.WXPAY_MINI) {
            wxRequest.setAppid(this.wxPayConfig.getMiniAppId());
        } else if (request.getPayTypeEnum() == BestPayTypeEnum.WXPAY_APP) {
            wxRequest.setAppid(this.wxPayConfig.getAppAppId());
        } else {
            wxRequest.setAppid(this.wxPayConfig.getAppId());
        }

        wxRequest.setMchId(this.wxPayConfig.getMchId());
        wxRequest.setNotifyUrl(this.wxPayConfig.getNotifyUrl());
        wxRequest.setNonceStr(RandomUtil.getRandomStr());
        wxRequest.setSpbillCreateIp(StringUtils.isEmpty(request.getSpbillCreateIp()) ? "8.8.8.8" : request.getSpbillCreateIp());
        wxRequest.setAttach(request.getAttach());
        wxRequest.setSign(WxPaySignature.sign(MapUtil.buildMap(wxRequest), this.wxPayConfig.getMchKey()));


        log.info( "-------------"+XmlUtil.toString(wxRequest));
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), XmlUtil.toString(wxRequest));
        Call<WxPaySyncResponse> call = ((WxPayApi)this.retrofit.create(WxPayApi.class)).unifiedorder(body);
        Response retrofitResponse = null;

        try {
            retrofitResponse = call.execute();
        } catch (IOException var7) {
            var7.printStackTrace();
        }

        assert retrofitResponse != null;

        if (!retrofitResponse.isSuccessful()) {
            throw new RuntimeException("【微信统一支付】发起支付, 网络异常");
        } else {
            WxPaySyncResponse response = (WxPaySyncResponse)retrofitResponse.body();

            assert response != null;

            if (!response.getReturnCode().equals("SUCCESS")) {
                throw new RuntimeException("【微信统一支付】发起支付, returnCode != SUCCESS, returnMsg = " + response.getReturnMsg());
            } else if (!response.getResultCode().equals("SUCCESS")) {
                throw new RuntimeException("【微信统一支付】发起支付, resultCode != SUCCESS, err_code = " + response.getErrCode() + " err_code_des=" + response.getErrCodeDes());
            } else {
                return this.buildPayResponse(response);
            }
        }
    }

    public boolean verify(Map map, SignType signType, String sign) {
        return WxPaySignature.verify(map, this.wxPayConfig.getMchKey());
    }

    public PayResponse syncNotify(HttpServletRequest request) {
        return null;
    }

    public PayResponse asyncNotify(String notifyData) {
        if (!WxPaySignature.verify(XmlUtil.toMap(notifyData), this.wxPayConfig.getMchKey())) {
            log.error("【微信支付异步通知】签名验证失败, response={}", notifyData);
            throw new RuntimeException("【微信支付异步通知】签名验证失败");
        } else {
            WxPayAsyncResponse asyncResponse = (WxPayAsyncResponse) XmlUtil.toObject(notifyData, WxPayAsyncResponse.class);
            if (!asyncResponse.getReturnCode().equals("SUCCESS")) {
                throw new RuntimeException("【微信支付异步通知】发起支付, returnCode != SUCCESS, returnMsg = " + asyncResponse.getReturnMsg());
            } else if (!asyncResponse.getResultCode().equals("SUCCESS") && asyncResponse.getErrCode().equals("ORDERPAID")) {
                return this.buildPayResponse(asyncResponse);
            } else if (!asyncResponse.getResultCode().equals("SUCCESS")) {
                throw new RuntimeException("【微信支付异步通知】发起支付, resultCode != SUCCESS, err_code = " + asyncResponse.getErrCode() + " err_code_des=" + asyncResponse.getErrCodeDes());
            } else {
                return this.buildPayResponse(asyncResponse);
            }
        }
    }

    public RefundResponse refund(RefundRequest request) {
        WxPayRefundRequest wxRequest = new WxPayRefundRequest();
        wxRequest.setOutTradeNo(request.getOrderId());
        wxRequest.setOutRefundNo(request.getOrderId());
        wxRequest.setTotalFee(MoneyUtil.Yuan2Fen(request.getOrderAmount()));
        wxRequest.setRefundFee(MoneyUtil.Yuan2Fen(request.getOrderAmount()));
        wxRequest.setAppid(this.wxPayConfig.getAppId());
        wxRequest.setMchId(this.wxPayConfig.getMchId());
        wxRequest.setNonceStr(RandomUtil.getRandomStr());
        wxRequest.setSign(WxPaySignature.sign(MapUtil.buildMap(wxRequest), this.wxPayConfig.getMchKey()));
        if (this.wxPayConfig.getSslContext() == null) {
            this.wxPayConfig.initSSLContext();
        }

        OkHttpClient okHttpClient = (new OkHttpClient()).newBuilder().sslSocketFactory(this.wxPayConfig.getSslContext().getSocketFactory()).addInterceptor((new HttpLoggingInterceptor()).setLevel(Level.BODY)).build();
        Retrofit retrofit = (new Builder()).baseUrl("https://api.mch.weixin.qq.com/").addConverterFactory(SimpleXmlConverterFactory.create()).client(okHttpClient).build();
        String xml = XmlUtil.toString(wxRequest);
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xml);
        Call<WxRefundResponse> call = ((WxPayApi)retrofit.create(WxPayApi.class)).refund(body);
        Response retrofitResponse = null;

        try {
            retrofitResponse = call.execute();
        } catch (IOException var10) {
            var10.printStackTrace();
        }

        if (!retrofitResponse.isSuccessful()) {
            throw new RuntimeException("【微信退款】发起退款, 网络异常");
        } else {
            WxRefundResponse response = (WxRefundResponse)retrofitResponse.body();
            if (!response.getReturnCode().equals("SUCCESS")) {
                throw new RuntimeException("【微信退款】发起退款, returnCode != SUCCESS, returnMsg = " + response.getReturnMsg());
            } else if (!response.getResultCode().equals("SUCCESS")) {
                throw new RuntimeException("【微信退款】发起退款, resultCode != SUCCESS, err_code = " + response.getErrCode() + " err_code_des=" + response.getErrCodeDes());
            } else {
                return this.buildRefundResponse(response);
            }
        }
    }

    public OrderQueryResponse query(OrderQueryRequest request) {
        WxOrderQueryRequest wxRequest = new WxOrderQueryRequest();
        wxRequest.setOutTradeNo(request.getOrderId());
        wxRequest.setTransactionId(request.getOutOrderId());
        wxRequest.setAppid(this.wxPayConfig.getAppId());
        wxRequest.setMchId(this.wxPayConfig.getMchId());
        wxRequest.setNonceStr(RandomUtil.getRandomStr());
        wxRequest.setSign(WxPaySignature.sign(MapUtil.buildMap(wxRequest), this.wxPayConfig.getMchKey()));
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), XmlUtil.toString(wxRequest));
        Call<WxOrderQueryResponse> call = ((WxPayApi)this.retrofit.create(WxPayApi.class)).orderquery(body);
        Response retrofitResponse = null;

        try {
            retrofitResponse = call.execute();
        } catch (IOException var7) {
            var7.printStackTrace();
        }

        assert retrofitResponse != null;

        if (!retrofitResponse.isSuccessful()) {
            throw new RuntimeException("【微信订单查询】网络异常");
        } else {
            WxOrderQueryResponse response = (WxOrderQueryResponse)retrofitResponse.body();

            assert response != null;

            if (!response.getReturnCode().equals("SUCCESS")) {
                throw new RuntimeException("【微信订单查询】returnCode != SUCCESS, returnMsg = " + response.getReturnMsg());
            } else if (!response.getResultCode().equals("SUCCESS")) {
                throw new RuntimeException("【微信订单查询】resultCode != SUCCESS, err_code = " + response.getErrCode() + ", err_code_des=" + response.getErrCodeDes());
            } else {
                return OrderQueryResponse.builder().orderStatusEnum(OrderStatusEnum.findByName(response.getTradeState())).resultMsg(response.getTradeStateDesc()).outTradeNo(response.getTransactionId()).orderId(response.getOutTradeNo()).attach(response.getAttach()).finishTime(response.getTimeEnd().replaceAll("(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})", "$1-$2-$3 $4:$5:$6")).build();
            }
        }
    }

    private RefundResponse buildRefundResponse(WxRefundResponse response) {
        RefundResponse refundResponse = new RefundResponse();
        refundResponse.setOrderId(response.getOutTradeNo());
        refundResponse.setOrderAmount(MoneyUtil.Fen2Yuan(response.getTotalFee()));
        refundResponse.setOutTradeNo(response.getTransactionId());
        refundResponse.setRefundId(response.getOutRefundNo());
        refundResponse.setOutRefundNo(response.getRefundId());
        return refundResponse;
    }

    private PayResponse buildPayResponse(WxPayAsyncResponse response) {
        PayResponse payResponse = new PayResponse();
        payResponse.setPayPlatformEnum(BestPayPlatformEnum.WX);
        payResponse.setOrderAmount(MoneyUtil.Fen2Yuan(response.getTotalFee()));
        payResponse.setOrderId(response.getOutTradeNo());
        payResponse.setOutTradeNo(response.getTransactionId());
        payResponse.setAttach(response.getAttach());
        payResponse.setMwebUrl(response.getMwebUrl());
        return payResponse;
    }

    private PayResponse buildPayResponse(WxPaySyncResponse response) {
        String timeStamp = String.valueOf(System.currentTimeMillis() / 1000L);
        String nonceStr = RandomUtil.getRandomStr();
        String packAge = "prepay_id=" + response.getPrepayId();
        String signType = "MD5";
        Map<String, String> map = new HashMap();
        map.put("appId", response.getAppid());
        map.put("timeStamp", timeStamp);
        map.put("nonceStr", nonceStr);
        map.put("package", packAge);
        map.put("signType", signType);
        PayResponse payResponse = new PayResponse();
        payResponse.setAppId(response.getAppid());
        payResponse.setTimeStamp(timeStamp);
        payResponse.setNonceStr(nonceStr);
        payResponse.setPackAge(packAge);
        payResponse.setSignType(signType);
        payResponse.setPaySign(WxPaySignature.sign(map, this.wxPayConfig.getMchKey()));
        payResponse.setMwebUrl(response.getMwebUrl());
        payResponse.setCodeUrl(response.getCodeUrl());
        return payResponse;
    }

    public String downloadBill(DownloadBillRequest request) {
        WxDownloadBillRequest wxRequest = new WxDownloadBillRequest();
        wxRequest.setBillDate(request.getBillDate());
        wxRequest.setAppid(this.wxPayConfig.getAppId());
        wxRequest.setMchId(this.wxPayConfig.getMchId());
        wxRequest.setNonceStr(RandomUtil.getRandomStr());
        wxRequest.setSign(WxPaySignature.sign(MapUtil.buildMap(wxRequest), this.wxPayConfig.getMchKey()));
        RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), XmlUtil.toString(wxRequest));
        Call<ResponseBody> call = ((WxPayApi)this.retrofit.create(WxPayApi.class)).downloadBill(body);
        Response retrofitResponse = null;

        try {
            retrofitResponse = call.execute();
        } catch (IOException var9) {
            var9.printStackTrace();
        }

        if (!retrofitResponse.isSuccessful()) {
            throw new RuntimeException("【微信订单查询】网络异常");
        } else {
            String response = null;

            try {
                response = ((ResponseBody)retrofitResponse.body()).string();
                if (response.startsWith("<")) {
                    WxDownloadBillResponse downloadBillResponse = (WxDownloadBillResponse)XmlUtil.toObject(response, WxDownloadBillResponse.class);
                    throw new RuntimeException("【对账文件】返回异常 错误码: " + downloadBillResponse.getErrorCode() + " 错误信息: " + downloadBillResponse.getReturnMsg());
                }
            } catch (IOException var8) {
                var8.printStackTrace();
            }

            return response;
        }
    }

    public String getQrCodeUrl(String productId) {
        String appid = this.wxPayConfig.getAppId();
        String mch_id = this.wxPayConfig.getMchId();
        String timeStamp = String.valueOf(System.currentTimeMillis() / 1000L);
        String nonceStr = RandomUtil.getRandomStr();
        Map<String, String> map = new HashMap();
        map.put("appid", appid);
        map.put("mch_id", mch_id);
        map.put("product_id", productId);
        map.put("time_stamp", timeStamp);
        map.put("nonce_str", nonceStr);
        return "weixin://wxpay/bizpayurl?appid=" + appid + "&mch_id=" + mch_id + "&product_id=" + productId + "&time_stamp=" + timeStamp + "&nonce_str=" + nonceStr + "&sign=" + WxPaySignature.sign(map, this.wxPayConfig.getMchKey());
    }
}

